#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "../include/hash.h"
#include "../include/addfile.h"
#include "../include/vfs_errorcodes.h"



int updateDataFile(char location[],char data[])
{
	FILE *fp;
	struct header h1;
	struct Block b1;
	struct freeList fl1;
	struct fileDescriptor *fd1;
	int i,j,n,size1,size2,blockno,freelistno,freefileDescriptor,index;
	freefileDescriptor=0;
	char datas[1024],newData[1024],fname[30],fileloc[100];
	//printf("in update\n");
	//scanf("%s",diskfilepath);
	strcpy(fileloc,location);
	//printf("loc:%s\ndata:%s\n",location,data);
	//fd1=searchBst(location);


//---------------------------------------------------------------------------------------------------------------------
//reading from text file

int fileSize = 0;
//printf("Opening file: \"%s\"\n", loc);
FILE *pFile = fopen(data, "r");
if(pFile == NULL){
//printf("error in openeing file");
}
fseek(pFile, 0, SEEK_END);
fileSize = ftell(pFile);
if(fileSize>1020)
{
printf("updatefile_FAILURE ");
printf(ERR_VFS_UPDATEFILE_03);
printf("\n");
return 0;
}
rewind(pFile);
char *data2 = (char*) calloc(sizeof(char), fileSize + 20);		
char *data1;
fread(data2, 1, fileSize, pFile);
if(ferror(pFile)){
//dbgError("fread()");
exit(1);
}
data1=datas;
while(*data1++ = *data2++)			//copying from character pointer to pointer array
      ;
//puts(datas);
fclose(pFile);

		
//---------------------------------------------------------------------------------------------------------------------
	//blockno=fd1->blockNumber;
	//printf("BlockNumber:%d\n",blockno);

	
	char * result =strtok(location,"/");
	while(result!=NULL)
	{
		strcpy(fname,result);
		result=strtok(NULL,"/");		
		
	}
	//printf("FNAME:%s\n",fname);

	struct linkedlist *ptr;
	index=hash(fname);
	ptr=hashtable[index];

	
		
	while(ptr!=NULL)
	{
		//printf("in while loop\n");
		if(strcmp(ptr->fd->locationPath,fileloc)==0)
		{
			//strcpy(fileloc,ptr->fd->locationPath);
			//printf("File name hash:%s\n",ptr->fName);
			//printf("File name fd:%s\n",ptr->fd->fileName);	
			//printf("File location:%s\n",ptr->fd->locationPath);
			//printf("File location:%d\n",ptr->fd->blockNumber);
			//printf("File location:%d\n",ptr->fd->fileSize);
			//printf("%s\n",fileloc);
			break;
		}
		else
		ptr=ptr->nextNode;
	}

	if(ptr==NULL)
	{
		printf("updatefile_FAILURE ");
	printf(ERR_VFS_UPDATEFILE_01);
	printf("\n");
	return 0;
	
	}


	fp=fopen(flsname,"rb+");
	fread(&h1,sizeof(struct header),1,fp);
	n=h1.maxfd;
	//------------------------------------------------------------------------------------------------------------------------
//updating to blockprintf
/*
	size1=sizeof(struct header)+n*sizeof(struct freeList);
	size2=(size1+(n*(sizeof(struct fileDescriptor)))+(ptr->fd->blockNumber*(sizeof(struct Block))));
	fseek(fp,size2,SEEK_SET);
		fread(&b1,sizeof(struct Block),1,fp);
			//printf("%c ",b1.isfull);
			if(b1.isfull=='1')
			{
				
				printf("\nFile contents : %s \n",b1.text);
				strcpy(newData,b1.text);
				
			}
		
	strcat(newData,data);*/
	if(strlen(datas)<1020)
	{
	size1=sizeof(struct header)+n*sizeof(struct freeList);
	size2=(size1+(n*(sizeof(struct fileDescriptor)))+(ptr->fd->blockNumber*(sizeof(struct Block))));
	fseek(fp,size2,SEEK_SET);
	b1.isfull='1';
	strcpy(b1.text,datas);
	fwrite(&b1,sizeof(struct Block),1, fp );
	//printf("NewData:%s\n",datas);
	}

	fclose(fp);
	return 1;
}

int searchFile(char name[],char flname[])
{
	int index;
	FILE *fpsearch;
	char fileloc[50];
	char H_name[20];
	index=hash(name);
	//printf("%d\n",index);
	int sz=strlen(name);	
	struct linkedlist *ptr;
	ptr=hashtable[index];

	fpsearch=fopen(flname,"r");
	if(fpsearch==NULL)
	return 1;

	fclose(fpsearch);
	fpsearch=fopen(flname,"w");
	int equalityflag=1;
	int i=0;

	while(ptr!=NULL)
	{
	//printf("in while loop\n");
	strcpy(H_name,ptr->fName);
	equalityflag=1;
	i=0;
	//printf("size %d\n",sz);
		while(equalityflag==1 && i<sz)
		{
		//printf("in 2nd while loop\n");
		//printf("EQFLG: %d  i: %d\n",equalityflag,i);
			if(H_name[i]==name[i])
			{
			//printf("%c %d\n",name[i],i);
			i++;
			}
			else
			{
			//printf("in else\n");
			equalityflag=0;
			}
		
			
		}

		if(equalityflag==1)
		{

		strcpy(fileloc,ptr->fd->locationPath);
		fprintf(fpsearch,"%s\n",fileloc);
		//printf("File name hash:%s\n",ptr->fName);
		//printf("File name fd:%s\n",ptr->fd->fileName);	
		//printf("File location:%s\n",fileloc);
		//printf("%s\n",fileloc);
		}
	
	ptr=ptr->nextNode;
	}

	fclose(fpsearch);
	return 0;
	
}


struct fileDescriptor * addDataFile(char location[],char name1[],char fileType[],char diskfilepath[])
{
	FILE *fp,*ft;
	struct fileDescriptor fd1,*fd2,*fd3;
	int i,j,n,size1,size2,blockno,freelistno,freefileDescriptor;
	freefileDescriptor=0;
	
	char datas[1024],bstloc[100];
	//printf("\nEnter path for source text file in local disk : ");
	//scanf("%s",diskfilepath);
	
	//printf("loc:%s\nname:%s\n",location,name1);
	strcpy(bstloc,location);
	strcat(bstloc,name1);
	fd3=searchBstfd(bstloc);
	if(fd3!=NULL)
	{
	printf("addfile_FAILURE ");
	printf(ERR_VFS_ADDFILE_03);
	printf("\n");
	return NULL;
	}
	else
	{
	//printf("not found\n");
	}
	
		
//---------------------------------------------------------------------------------------------------------------------
//reading from text file

int fileSize = 0;
//printf("Opening file: \"%s\"\n", loc);
FILE *pFile = fopen(diskfilepath, "r");
if(pFile == NULL){
//printf("error in openeing file");
}
fseek(pFile, 0, SEEK_END);
fileSize = ftell(pFile);
if(fileSize>1020)
{
printf("addfile_FAILURE ");
printf(ERR_VFS_ADDFILE_06);
printf("\n");
return NULL;

}
rewind(pFile);
char *data = (char*) calloc(sizeof(char), fileSize + 20);
char *data1;
fread(datas, 1, fileSize, pFile);
/*if(ferror(pFile)){
//dbgError("fread()");
exit(1);
}
data1=datas;
while(*data1++ = *data++)			//copying from character pointer to pointer array
      ;
//puts(data);*/
fclose(pFile);
//fd2=addFDFile1(location,name1,datas);
fd2=addFDFile1(location,name1,fileType,datas,fileSize);
//fd2 = addFDFile1(location,name1,datas);
//---------------------------------------------------------------------------------------------------------------------
return fd2;
}
struct fileDescriptor * addFDFile1(char location[],char name1[],char fileType[],char datas[],int size_of_file)
{
	int i,j,k,n,size1,size2,blockno,freelistno,freefileDescriptor;
	freefileDescriptor=0;
	FILE *fp,*ft;
	struct header h1;
	struct Block b1;
	struct freeList fl1;
	struct fileDescriptor *fd1,*fd2;
	fd1=(struct fileDescriptor *)malloc(sizeof(struct fileDescriptor));

	//printf("%s\n%s\n%s\n",name1,flsname,location);	
	
	//printf("in adddatafile\n");
	//fgets(datas, sizeof(datas), stdin);
	fp=fopen(flsname,"rb+");
	if(fp==NULL)
	{
		printf("addfile_FAILURE ");
		printf(ERR_VFS_ADDFILE_05);
		printf("\n");
		return NULL;

	}
	fread(&h1,sizeof(struct header),1,fp);
	n=h1.maxfd;
	fseek(fp,sizeof(struct header),SEEK_SET);
	//printf("Number:%d",n);
//---------------------------------------------------------------------------------------------------------------------
//searching for free list 	
	for(i=0;i<n;i++)
	{
		fread(&fl1,sizeof(struct freeList),1,fp);
		if(fl1.freel == '0')
		{
			fl1.freel = '1';
			size1=sizeof(struct header)+i*sizeof(struct freeList);
			fseek(fp,size1,SEEK_SET);
			fwrite(&fl1,sizeof(struct freeList),1, fp );
			freelistno=i;
			//printf("freelist:%c\n",fl1.freel);
			//printf("Number:%d\n",i);
			break;
		}
	}
//------------------------------------------------------------------------------------------------------------------------
//searching for free file descriptor
	size1=sizeof(struct header)+n*sizeof(struct freeList);
	fseek(fp,size1,SEEK_SET);
	
	fd1->blockNumber=freelistno;
	for(i=0;i<n;i++)
	{
		fread(fd1,sizeof(struct fileDescriptor),1,fp);
		if(fd1->isfull == '0')
		{
			freefileDescriptor=1;
			blockno=i;
			fd1->isfull='1';
			fd1->blockNumber=freelistno;
			//strcpy(fd1->fileType,"text");
			strcpy(fd1->fileType,fileType);
			strcpy(fd1->locationPath,location);
			fd1->fileSize=size_of_file;
			break;
		}
		
	}
		if(freefileDescriptor==0)
		{
			return NULL;
		}

//----------------------------------------------------------------------------------------------------------------------
//writing data to blocks
	size1=sizeof(struct header)+n*sizeof(struct freeList);
		size2=(size1+(n*(sizeof(struct fileDescriptor)))+(freelistno*(sizeof(struct Block))));
	fseek(fp,size2,SEEK_SET);
	for(k=0;k<size_of_file;k++)
			b1.text[k]=datas[k];	


	b1.isfull='1';
	fwrite(&b1,sizeof(struct Block),1, fp );
	//printf("\nFile written to disk\n");
	

//------------------------------------------------------------------------------------------------------------------------
	fseek(fp,sizeof(struct header),SEEK_SET);
	for(i=0;i<10;i++)
	{
		//printf("flist->");
		fread(&fl1,sizeof(struct freeList),1,fp);
		//printf("%c ",fl1.freel);
		
	}
	//printf("\n");
	/*for(i=0;i<n;i++)
	{
		fread(&fd1,sizeof(struct fileDescriptor),1,fp);
		printf("%c ",fd1.isfull);
	}*/
	size1=sizeof(struct header)+n*sizeof(struct freeList);
	size2=(size1+(n*(sizeof(struct fileDescriptor)))+(freelistno*(sizeof(struct Block))));
	fseek(fp,size2,SEEK_SET);
	//printf("\n");
	/*for(i=0;i<n;i++)
	{
		fread(&b1,sizeof(struct Block),1,fp);
		printf("%c ",b1.isfull);
		if(b1.isfull=='1');
		printf("\nFile contents : %s \n",b1.text);
	}*/
	fclose(fp);
	strcpy(fd1->fileName,"");
	strcpy(fd1->fileName,name1);
	strcpy(fd1->fileType,"");
	strcpy(fd1->fileType,fileType);
	fd2=fd1;
	//printf("\nin addfd file : %s \n",fd2->fileName);
	//printf("\nin addfd file : %s \n",fd2->fileType);
	return fd2;
}
//---------------------------------------------------------------------------------------------------------------
//displays the contents of each file from the file system 
void displayfiles(char fsname[])
{
	struct header h1;
	struct Block b1;
	struct freeList fl1;
	struct fileDescriptor fd1;
	int i,n;
	
	FILE *fp;	
	fp=fopen(fsname,"rb+");
	fread(&h1,sizeof(struct header),1,fp);
	n=h1.maxfd;	
	int size1=sizeof(struct header)+n*sizeof(struct freeList);
	int size2=(size1+(n*(sizeof(struct fileDescriptor))));
	
	fseek(fp,size2,SEEK_SET);
	printf("\n");
	for(i=0;i<n;i++)
	{
		fread(&b1,sizeof(struct Block),1,fp);
		//printf("%c ",b1.isfull);
		if(b1.isfull=='1')
		{
			printf("----------------------------------------------------------------------");
			printf("\nFile contents : %s \n",b1.text);
			printf("----------------------------------------------------------------------");	
		}
	}
	fclose(fp);
	
}

int exportfile1(char vfsFilePath[],char hardDiskPath[])
{
	FILE *fs,*ft;
	char ch;
	char srcfilelocation[100],destfilelocation[100];
	strcpy(srcfilelocation,vfsFilePath);
	strcpy(destfilelocation,hardDiskPath);
	
	//Seeking to the specified location in the file system--------------
	struct header h1;
	struct Block b1;
	struct freeList fl1;
	struct fileDescriptor *fd1,*fd3;

	int i,j,n,size1,size2,blockno,freelistno,freefileDescriptor,index;
	freefileDescriptor=0;
	char datas[1024],newData[1024],fname[30],fileloc[100];
	//printf("in update\n");
	//scanf("%s",diskfilepath);
	
	strcpy(fileloc,srcfilelocation);
	
	//fd1=searchBst(srcfilelocation);
		
	//blockno=fd1->blockNumber;
	//printf("BlockNumber:%d\n",blockno);

	
	char * result =strtok(srcfilelocation,"/");
	while(result!=NULL)
	{
		strcpy(fname,result);
		result=strtok(NULL,"/");		
		
	}
	//printf("FNAME:%s\n",fname);

	struct linkedlist *ptr;
	index=hash(fname);
	ptr=hashtable[index];

	//printf("before while loop\n");
		
	while(ptr!=NULL)
	{
		//printf("in while loop\n");
		if(strcmp(ptr->fd->locationPath,fileloc)==0)
		{
			//strcpy(fileloc,ptr->fd->locationPath);
			//printf("File name hash:%s\n",ptr->fName);
			//printf("File name fd:%s\n",ptr->fd->fileName);	
			//printf("File location:%s\n",ptr->fd->locationPath);
			//printf("File location:%d\n",ptr->fd->blockNumber);
			//printf("File location:%d\n",ptr->fd->fileSize);
			//printf("%s\n",fileloc);
				break;
		}
		else
		ptr=ptr->nextNode;
	}
	
	
	//printf("%s\n",fileloc );
	fd3=searchBstfd(fileloc);
	if(fd3!=NULL)
	{
	
		//printf("\n");
		//printf("ftype:%s\n",fd3->fileType);	
		//printf("ftype:%s\n",fd3->fileName);
	
		if(strcmp(fd3->fileType,"dir")==0)
		{
			printf("exportfile_FAILURE ");
			printf(ERR_VFS_EXPORTFILE_03);
			printf("\n");
			return NULL;
		}
	}		

	
	if (ptr == NULL)
	{	
		//ERR_VFS_EXPORTFILE_01 "CANNOT_FIND_SOURCEFILE"
		printf("exportfile_FAILURE ");
		printf(ERR_VFS_EXPORTFILE_01);
		printf("\n");
		return NULL;
	}
	
	else
	{	
		//srcfile-----------------------------------------------------------	
		fs = fopen(flsname,"rb+");
		fread(&h1,sizeof(struct header),1,fs);
		n=h1.maxfd;
		size1=sizeof(struct header)+n*sizeof(struct freeList);
		size2=(size1+(n*(sizeof(struct fileDescriptor)))+(ptr->fd->blockNumber*(sizeof(struct Block))));
		fseek(fs,size2,SEEK_SET);
	
		// write to the dest file---------------------------------------
		ft = fopen(destfilelocation,"wb+");
		if(ft==NULL)
		{	
			//ERR_VFS_EXPORTFILE_02 "CANNOT_CREATE_OUTPUTFILE"
			printf("exportfile_FAILURE ");
			printf(ERR_VFS_EXPORTFILE_02);
			printf("\n");
			return NULL;
		}
		else
			{
				while(1)
				{
					ch = fgetc(fs);
					if(ch=='\0')
					break;
					fputc(ch,ft);
					//printf("%c",ch); 

				}
  
				fclose(fs);
				fclose(ft);
				printf("exportfile_SUCCESS");
				printf("\n");
			}	
	
	}	
}
